package gamelogic

import (
	"server_cluster/common/config"
	"server_cluster/common/gdconf"
	"server_cluster/common/logger"
	"server_cluster/common/mysock"
	"server_cluster/common/protoc/pb"
	"server_cluster/logic/sharemem"
)

func AddUserMail(title string, content string, sender string, expireTime uint32, isImportance bool, itemMap map[int32]int32, user *sharemem.User) {
	ok, mailId := user.AddMail(title, content, sender, expireTime, isImportance, itemMap)
	if !ok {
		logger.Error("add mail fail, uid: %v", user.GetUid())
		return
	}
	mail := user.GetMail(mailId)
	SendMsg(config.SC_MailAddNotify, &pb.SC_MailAddNotify{MailList: []*pb.Mail{user.PacketUserMail(mail)}}, nil, user)
}

func AcceptTimerMail(user *sharemem.User) {
	var maxMailId int32 = 0
	for _, mailConfig := range gdconf.GetMailConfigMap() {
		if mailConfig.SendType != gdconf.MailSendTypeTime {
			continue
		}
		if sharemem.MyShm.TimeNow < mailConfig.SendTime.Unix() {
			continue
		}
		if uint64(mailConfig.MailId) <= user.TimerMailId {
			continue
		}
		itemMap := make(map[int32]int32)
		for _, item := range mailConfig.ItemList {
			itemMap[item.ItemId] += item.ItemCount
		}
		expireTime := uint32(mailConfig.SendTime.Unix() + int64(mailConfig.SendExpireHour*3600))
		if expireTime != 0 && expireTime < uint32(sharemem.MyShm.TimeNow) {
			continue
		}
		AddUserMail(mailConfig.Title, mailConfig.Content, mailConfig.Sender, expireTime, mailConfig.Importance, itemMap, user)
		if maxMailId < mailConfig.MailId {
			maxMailId = mailConfig.MailId
		}
	}
	if maxMailId != 0 {
		// 刷新当前id
		user.SetTimerMailId(uint64(maxMailId))
	}
}

//=========消息协议处理==============

func GetAllMailReq(user *sharemem.User, buf *mysock.SockBuf) int16 {
	req, ok := ParseMsg(config.CS_GetAllMailReq, new(pb.CS_GetAllMailReq), buf, user).(*pb.CS_GetAllMailReq)
	if !ok {
		return config.PROTO_ERROR
	}
	_ = req

	user.ClearAllExpireMail()
	mailList := user.GetMailList()
	pbMailList := make([]*pb.Mail, 0)
	for _, mail := range mailList {
		pbMailList = append(pbMailList, user.PacketUserMail(mail))
	}

	return SendMsg(config.SC_GetAllMailRsp, &pb.SC_GetAllMailRsp{RetCode: config.OK, MailList: pbMailList}, buf, user)
}

func GetMailItemReq(user *sharemem.User, buf *mysock.SockBuf) int16 {
	req, ok := ParseMsg(config.CS_GetMailItemReq, new(pb.CS_GetMailItemReq), buf, user).(*pb.CS_GetMailItemReq)
	if !ok {
		return config.PROTO_ERROR
	}

	mailIdList := make([]int32, 0)
	if req.GetAll {
		for _, mail := range user.GetMailList() {
			if mail.IsAttachmentGot {
				continue
			}
			if len(mail.GetItemList()) == 0 {
				continue
			}
			mailIdList = append(mailIdList, mail.GetId())
		}
	} else {
		mailIdList = append(mailIdList, req.MailId)
	}
	pbItemList := make([]*pb.Item, 0)
	for _, mailId := range mailIdList {
		mail := user.GetMail(mailId)
		if mail == nil {
			logger.Error("get mail is nil, mailId: %v, uid: %v", mailId, user.GetUid())
			continue
		}
		if mail.IsAttachmentGot {
			logger.Error("mail item already got, mailId: %v, uid: %v", mailId, user.GetUid())
			continue
		}
		itemList := mail.GetItemList()
		itemMap := make(map[int32]int32)
		itemNum4Type := make(map[int32]int32)
		for _, item := range itemList {
			pbItemList = append(pbItemList, &pb.Item{Id: item.ItemId, Num: item.Count})
			itemMap[item.ItemId] += item.Count
			var itemCfg = gdconf.GetItemConfig(item.ItemId)
			if itemCfg != nil {
				itemNum4Type[itemCfg.Type] += item.Count
			}
		}
		var ret = CheckBags(itemNum4Type, user)
		if ret != config.OK {
			return SendMsg(config.SC_GetMailItemRsp, &pb.SC_GetMailItemRsp{RetCode: ret}, buf, user)
		}
		ret = AddItems(itemMap, user)
		if ret != config.OK {
			logger.Error("add item error, ret: %v, uid: %v", ret, user.GetUid())
		}
		mail.IsRead = true
		mail.IsAttachmentGot = true
		mail.SetSync()
	}

	return SendMsg(config.SC_GetMailItemRsp, &pb.SC_GetMailItemRsp{RetCode: config.OK, ItemList: pbItemList}, buf, user)
}

func DelMailReq(user *sharemem.User, buf *mysock.SockBuf) int16 {
	req, ok := ParseMsg(config.CS_DelMailReq, new(pb.CS_DelMailReq), buf, user).(*pb.CS_DelMailReq)
	if !ok {
		return config.PROTO_ERROR
	}

	mailIdList := make([]int32, 0)
	if req.DeleteAllRead {
		for _, mail := range user.GetMailList() {
			if !mail.IsRead {
				continue
			}
			if mail.IsImportance {
				continue
			}
			mailIdList = append(mailIdList, mail.GetId())
		}
	} else {
		mailIdList = append(mailIdList, req.MailId)
	}
	for _, mailId := range mailIdList {
		user.DelMail(mailId)
	}

	return SendMsg(config.SC_DelMailRsp, &pb.SC_DelMailRsp{RetCode: config.OK}, buf, user)
}

func ReadMailReq(user *sharemem.User, buf *mysock.SockBuf) int16 {
	req, ok := ParseMsg(config.CS_ReadMailReq, new(pb.CS_ReadMailReq), buf, user).(*pb.CS_ReadMailReq)
	if !ok {
		return config.PROTO_ERROR
	}

	mail := user.GetMail(req.MailId)
	if mail == nil {
		logger.Error("get mail is nil, mailId: %v, uid: %v", req.MailId, user.GetUid())
		return SendMsg(config.SC_ReadMailRsp, &pb.SC_ReadMailRsp{RetCode: config.SERVER_ERROR}, buf, user)
	}
	mail.IsRead = true
	if len(mail.GetItemList()) == 0 {
		mail.IsAttachmentGot = true
	}
	mail.SetSync()

	return SendMsg(config.SC_ReadMailRsp, &pb.SC_ReadMailRsp{RetCode: config.OK}, buf, user)
}
